package com.zsw.dubbo.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtil {

	private static String base64EncodeString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	private static char[] base64EncodeChar = base64EncodeString.toCharArray();
	private static final String[] CHARS = new String[] { "a", "b", "c", "d",
			"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
			"r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3",
			"4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G",
			"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
			"U", "V", "W", "X", "Y", "Z" };

	private final static byte[] hex = "0123456789ABCDEF".getBytes();
	/**
	 * 0
	 */
	public static final int ALIGN_LEFT = 0;
	/**
	 * 1
	 */
	public static final int ALIGN_RIGHT = 1;
	/**
	 * 2
	 */
	public static final int ALIGN_CENTER = 2;

	/**
	 * String 类型的非空验证</br> 验证方式!=null,length()>0
	 * 
	 * @param objs
	 *            传入对象,处理时会调用toString()方法转型
	 * @return 非空返回true,如果参数中的某一成员对象为null或字符串长度==0,则返回false
	 */
	public static boolean stringProving(Object... objs) {
		boolean b = true;
		if (objs == null) {
			return false;
		}
		for (Object o : objs) {
			if (o == null || o.toString().length() == 0) {
				b = false;
				break;
			}
		}
		return b;
	}

	/**
	 * 文本取左,本方法不改变原文本内容!
	 * 
	 * @param str
	 *            欲取的原文本
	 * @param length
	 *            取出长度
	 * @return 截取后的文本
	 */
	public static String stringLeft(String str, int length) {
		return str.substring(0, length);
	}

	public static String stringRight(String str, int length) {
		return str.substring(str.length() - length, length);
	}

	public static String stringMLeft(String str, int length) {
		return str.substring(length);
	}

	/**
	 * 从右侧开始删除length位
	 * 
	 * @param str
	 *            原始字符串
	 * @param length
	 *            删除长度
	 * @return 处理后的字符串
	 */
	public static String stringMRight(String str, int length) {
		return str.substring(0, str.length() - length);
	}

	/**
	 * 字符串长度补齐方法
	 * 
	 * @param str
	 *            原字符串
	 * @param addStr
	 *            补齐使用字符串
	 * @param align
	 *            为0则左对齐{@link AllUtil#ALIGN_LEFT},1右对齐
	 *            {@link AllUtil#ALIGN_RIGHT},2居中对齐 {@link AllUtil#ALIGN_CENTER}
	 * @param length
	 *            补齐后长度
	 * @return 处理后的字符串
	 */
	public static String strAdd(String str, String addStr, int align, int length) {
		if (str == null) {
			return null;
		}
		if (addStr == null || addStr.equals("")) {
			addStr = " ";
		}
		if (align < 0 || align > 2) {
			align = 0;
		}
		switch (align) {
		case ALIGN_LEFT:
			while (getLength(str) < length) {
				str += addStr;
			}
			break;
		case ALIGN_RIGHT:
			while (getLength(str) < length) {
				str = addStr + str;
			}
			break;
		case ALIGN_CENTER:
			while (getLength(str) < length) {
				str = addStr + str + addStr;
			}
			break;
		default:
			break;
		}
		if (getLength(str) > length) {
			str = str.substring(0, length);
		}
		return str;

	}

	/**
	 * 将字符串首字母转换为大写
	 * 
	 * @param str
	 *            原始字符串
	 * @return 处理后的字符串
	 */
	public static String nToN(String str) {
		String n = stringLeft(str, 1);
		n = n.toUpperCase();
		str = n + str.substring(1);
		return str;
	}

	/**
	 * 取得字符串的绝对长度,汉字占长度2,英文数字与符号占长度1
	 * 
	 * @param value
	 *            欲取得其长度的字符串
	 * @return 字符串长度
	 */
	public static int getLength(String value) {
		int valueLength = 0;
		String chinese = "[\u4e00-\u9fa5]";
		for (int i = 0; i < value.length(); i++) {
			String temp = value.substring(i, i + 1);
			if (temp.matches(chinese)) {
				valueLength += 2;
			} else {
				valueLength += 1;
			}
		}
		return valueLength;
	}

	/**
	 * 中文转换为16进制Unicode
	 * 
	 * @param str
	 *            欲转换的中文字符串
	 * @return 转换后的Unicode串(例:你好 = \u4f60\u597d)
	 */
	public static String GBK2Unicode16(String str) {
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			char chr1 = (char) str.charAt(i);
			if (!isNeedConvert(chr1)) {
				result.append(chr1);
				continue;
			}
			result.append("\\u" + Integer.toHexString((int) chr1));
		}
		return result.toString();
	}

	/**
	 * 中文转换为10进制Unicode
	 * 
	 * @param str
	 *            欲转换的中文字符串
	 * @return 转换后的Unicode串(例:你好 = & # 20320 & # 22909)
	 */
	public static String GBK2Unicode10(String str) {
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			char chr1 = (char) str.charAt(i);
			if (!isNeedConvert(chr1)) {
				result.append(chr1);
				continue;
			}
			result.append("&#" + Integer.toString((int) chr1));
		}
		return result.toString();
	}

	/**
	 * 是否需要转换
	 * 
	 * @param para
	 * @return
	 */
	private static boolean isNeedConvert(char para) {
		return ((para & (0x00FF)) != para);
	}

	/**
	 * 16进制Unicode转换为中文字符串
	 * 
	 * @param unicode
	 * @return
	 */
	public static String Unicode2GBK16(String unicode) {
		return Unicode2GBK(unicode, 16);

	}

	/**
	 * 10进制Unicode转换为中文字符串
	 * 
	 * @param unicode
	 * @return
	 */
	public static String Unicode2GBK10(String unicode) {
		return Unicode2GBK(unicode, 10);
	}

	private static String Unicode2GBK(String unicode, int size) {
		int titleSize = 2;
		int x = 0;
		String title = null;
		int codeSize = 0;
		switch (size) {
		case 10:
			title = "&#";
			codeSize = 7;
			break;
		case 16:
			title = "\\u";
			codeSize = 6;
			break;
		default:
			return null;
		}
		while ((x = unicode.indexOf(title)) >= 0) {
			String code = unicode.substring(x, x + codeSize);
			char ch = (char) Integer.parseInt(code.substring(titleSize), size);
			if (code.startsWith("\\") && !code.startsWith("\\\\"))
				code = "\\" + code;
			unicode = unicode.replaceAll(code, ch + "");
		}
		return unicode;

		// int n = unicode.length() / s;
		// StringBuilder sb = new StringBuilder(n);
		// for (int i = 0, j = 2; i < n; i++, j += s) {
		// String code = unicode.substring(j, j + s2);
		// char ch = (char) Integer.parseInt(code, size);
		// sb.append(ch);
		// }
		// return sb.toString();
	}

	private static int parse(char c) {
		if (c >= 'a')
			return (c - 'a' + 10) & 0x0f;
		if (c >= 'A')
			return (c - 'A' + 10) & 0x0f;
		return (c - '0') & 0x0f;
	}

	/**
	 * 从字节数组到十六进制字符串转换
	 * 
	 * @param b
	 * @return
	 */
	public static String Bytes2HexString(byte[] b) {
		byte[] buff = new byte[2 * b.length];
		for (int i = 0; i < b.length; i++) {
			buff[2 * i] = hex[(b[i] >> 4) & 0x0f];
			buff[2 * i + 1] = hex[b[i] & 0x0f];
		}
		return new String(buff);
	}

	/**
	 * 从十六进制字符串到字节数组转换
	 * 
	 * @param hexstr
	 * @return
	 */
	public static byte[] HexString2Bytes(String hexstr) {
		byte[] b = new byte[hexstr.length() / 2];
		int j = 0;
		for (int i = 0; i < b.length; i++) {
			char c0 = hexstr.charAt(j++);
			char c1 = hexstr.charAt(j++);
			b[i] = (byte) ((parse(c0) << 4) | parse(c1));
		}
		return b;
	}

	/**
	 * 取32位随机数
	 * 
	 * @return
	 */
	public static String get32Char() {
		String sjs = "";
		Random r = new Random();
		for (int i = 0; i < 32; i++) {// 构造随机串
			sjs += base64EncodeChar[r.nextInt(64)];
		}
		return sjs;
	}

	/**
	 * 判断字符串编码格式
	 * 
	 * @param str
	 * @return
	 */
	public static String getEncoding(String str) {
		String[] encodes = { "ISO-8859-1", "GB2312", "GBK", "UTF-8" };
		for (String encode : encodes) {
			try {
				if (str.equals(new String(str.getBytes(encode), encode))) {
					return encode;
				}
			} catch (Exception exception) {
			}
		}
		return "";
	}

	/**
	 * 得到指定长度的空格符
	 * 
	 * @param size
	 * @return
	 */
	public static String getBlanks(int size) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < size; i++) {
			sb.append(" ");
		}
		return sb.toString();
	}

	/**
	 * 判断字符串是否是乱码
	 * 
	 * @param strName
	 *            字符串
	 * @return 是否是乱码
	 */
	public static boolean isMessyCode(String strName) {
		Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*");
		Matcher m = p.matcher(strName);
		String after = m.replaceAll("");
		String temp = after.replaceAll("\\p{P}", "");
		char[] ch = temp.trim().toCharArray();
		float chLength = ch.length;
		float count = 0;
		for (int i = 0; i < ch.length; i++) {
			char c = ch[i];
			if (!Character.isLetterOrDigit(c)) {
				if (!isChinese(c)) {
					count = count + 1;
				}
			}
		}
		float result = count / chLength;
		if (result > 0.4) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * 判断字符是否是中文
	 * 
	 * @param c
	 *            字符
	 * @return 是否是中文
	 */
	public static boolean isChinese(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
				|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
				|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
			return true;
		}
		return false;
	}

	/**
	 * 判断某一字符串是否可以匹配对应类型的正则规则
	 * 
	 * @param str
	 *            做匹配的原字符串
	 * @param regex
	 *            对应的正则表达式
	 * @return 某一参数为空或正则匹配失败返回false,否则返回true
	 */
	// @Deprecated
	// public static boolean isRegex(String str, String regex) {
	// if (stringProving(str, regex)) {
	// Matcher m = Pattern.compile(regex).matcher(str);
	// return m.find();
	// }
	// return false;
	// }

	/**
	 * 判断某一字符串是否可以匹配对应类型的正则规则
	 * 
	 * @param regex
	 *            对应的正则表达式
	 * @param strs
	 *            做匹配的字符串数组
	 * @return 某一参数为空或数组中任意一个正则匹配失败返回false,否则返回true
	 */
	public static boolean isRegex(String regex, String... strs) {
		if (stringProving(strs, regex)) {
			for (String s : strs) {
				Matcher m = Pattern.compile(regex).matcher(s);
				if (!m.find()) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	/**
	 * char类型非空验证
	 * 
	 * @param o
	 *            欲验证对象
	 * @return 非char返回0,是char且非空返回1,是char且为空返回2
	 */
	public static int charYN(Object o) {
		if (o == null) {
			throw new NullPointerException();
		}
		if (Character.class == o.getClass()) {
			if (((Character) o) == '\u0000') {
				return 2;
			} else {
				return 1;
			}
		} else {
			return 0;
		}
	}

	/**
	 * 取得16位全球唯一编码,包含分割线
	 * 
	 * @return 16位全球唯一编码
	 */
	public static String getUUID32A() {
		UUID uuid = UUID.randomUUID();
		return uuid.toString();
	}

	/**
	 * 取得16位全球唯一编码, <b>不包含</b> 分割线
	 * 
	 * @return 16位全球唯一编码
	 */
	public static String getUUID32() {
		return getUUID32A().replaceAll("-", "");
	}

	public static String[] getUUID32(int size) {
		String[] ss = new String[size];
		for (int i = 0; i < ss.length; i++) {
			ss[i] = getUUID32();
		}
		return ss;
	}

	public static String getUUID16() {
		return getUUIDShort() + getUUIDShort();
	}

	/**
	 * 利用62个可打印字符，通过随机生成32位UUID，由于UUID都为十六进制，所以将UUID分成8组，每4个为一组，然后通过模62操作，
	 * 结果作为索引取出字符， 这样重复率大大降低。</br> <b>百万级左右有可能发生重复,请酌情考虑使用环境</b>
	 * 
	 * @param args
	 */
	public static String getUUIDShort() {
		StringBuffer shortBuffer = new StringBuffer();
		String uuid = getUUID32();
		for (int i = 0; i < 8; i++) {
			String str = uuid.substring(i * 4, i * 4 + 4);
			int x = Integer.parseInt(str, 16);
			shortBuffer.append(CHARS[x % 0x3E]);
		}
		return shortBuffer.toString();
	}

	public static void main(String[] args) {

		Map<String, Integer> map = new HashMap<String, Integer>();

		try {
			while (true) {
				String s = getUUIDShort();
				if (map.containsKey(s)) {
					throw new Exception(map.size() + "发现重复" + s + ":"
							+ map.get(s));
				} else {
					map.put(s, map.size());
				}
				if (map.size() % 1000000 == 0) {
					System.out.println(map.size());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
